﻿using System;
using System.ComponentModel;
using SharpRomans.Exceptions;

namespace SharpRomans.ParsingRules
{
	[Description("7")]
	internal class Zero : IObserver<char>
	{
		private IState _state;
		private readonly string _literal;

		public Zero(string literal)
		{
			_literal = literal;
			_state = new Initial();
		}

		void TranstitionTo(IState next)
		{
			_state = next;
		}

		interface IState
		{
			void WithCharacter(char c, Zero rule);
		}

		class Initial : IState
		{
			public void WithCharacter(char c, Zero rule)
			{
				IState next = RomanFigure.N.Equals(c) ?
					   (IState)new NIsFirst() :
					   new NIsNotFirst();

				rule.TranstitionTo(next);
			}
		}

		class NIsFirst : IState
		{
			public void WithCharacter(char c, Zero rule)
			{
				// N must be the only figure in the literal
				throw new ParseException(rule._literal, rule._characterCounter);
			}
		}

		class NIsNotFirst : IState
		{
			public void WithCharacter(char c, Zero rule)
			{
				// N must be the only figure in the literal
				if (RomanFigure.N.Equals(c)) throw new ParseException(rule._literal, rule._characterCounter);
			}
		}

		private int _characterCounter;
		public void OnNext(char value)
		{
			_state.WithCharacter(value, this);
			_characterCounter++;
		}

		public void OnError(Exception error)
		{
			throw error;
		}

		public void OnCompleted()
		{

		}
	}
}
